
/* Header implementation of the double linked lists */

#ifndef D_LINKEDLIST_HEADER
#define D_LINKEDLIST_HEADER

#define DLNODE(name,type) \
typedef struct s_##name name; \
struct s_##name { \
    name *prev; \
    name *next; \
    type data; \
}

#define DLLIST(name,type) \
typedef struct s_##name name; \
struct s_##name { \
    type *firstNode; \
    type *lastNode; \
    int n; \
}

#define GEN_DLL_INSERTAFTER(name, typelist, typenode) \
void name (typelist *list, typenode *node, typenode *newNode) { \
    newNode->prev = node; \
    newNode->next = node->next; \
    if (node->next == NULL) \
        list->lastNode = newNode; \
    else \
        node->next->prev = newNode; \
    node->next = newNode; \
     \
    list->n++; \
}

#define GEN_DLL_INSERTBEFORE(name, typelist, typenode) \
void name (typelist *list, typenode *node, typenode *newNode) { \
    newNode->prev = node->prev; \
    newNode->next = node; \
    if (node->prev == NULL) \
        list->firstNode = newNode; \
    else \
        node->prev->next = newNode; \
    node->prev = newNode; \
    \
    list->n++; \
}

#define GEN_DLL_INSERTBEGINNING(name, nameinsertbefore, typelist, typenode) \
void name (typelist *list, typenode *newNode) { \
    if (list->firstNode == NULL) { \
        list->firstNode = newNode; \
        list->lastNode = newNode; \
        newNode->prev = NULL; \
        newNode->next = NULL; \
        \
        list->n++; \
    } \
    else \
        nameinsertbefore (list, list->firstNode, newNode); \
}

#define GEN_DLL_INSERTEND(name, nameinsertbeginning, nameinsertafter, typelist, typenode) \
void name (typelist *list, typenode *newNode) { \
    if (list->lastNode == NULL) \
        nameinsertbeginning (list, newNode); \
    else \
        nameinsertafter (list, list->lastNode, newNode); \
}

#define GEN_DLL_REMOVE(name, typelist, typenode) \
typenode *name (typelist *list, typenode *node) { \
    if (node->prev == NULL) \
        list->firstNode = node->next; \
    else \
        node->prev->next = node->next; \
    \
    if (node->next == NULL) \
        list->lastNode = node->prev; \
    else \
        node->next->prev = node->prev; \
    \
    node->prev = NULL; \
    node->next = NULL; \
    \
    list->n--; \
    \
    return(node); \
}

#define GEN_DLL_NEWNODE(name, typedata, typenode) \
typenode *name (typedata data) { \
    typenode *node; \
    node=malloc(sizeof(typenode)); \
    node->data=data; \
    node->prev=NULL; \
    node->next=NULL; \
    \
    return(node); \
}

#define GEN_DLL_FREENODE(name, typenode) \
int name (typenode *node) { \
    if (node != NULL) \
        free(node); \
    else \
        return 1; \
    \
    return 0; \
}

#define GEN_DLL_NEWLIST(name, typelist) \
typelist *name () { \
    typelist* l; \
    l=malloc(sizeof(typelist)); \
    l->firstNode = NULL; \
    l->lastNode = NULL; \
    l->n=0; \
    \
    return(l); \
}

#define GEN_DLL_FREELIST(name, namedllfreenode, typelist, typenode) \
int name (typelist *list) { \
    typenode *tmp, *tmp2; \
    int i; \
    \
    if (list != NULL) { \
        tmp = list->firstNode; \
        for (i=0; i<list->n; i++) { \
            tmp2 = tmp->next; \
            namedllfreenode (tmp); \
            tmp=tmp2; \
        } \
        free(list); \
    } \
    else \
        return 1; \
    \
    return 0; \
}

/**/
#define GEN_DLL_INSERTAFTER_D(name, typelist, typenode) \
void name (typelist *list, typenode *node, typenode *newNode);

#define GEN_DLL_INSERTBEFORE_D(name, typelist, typenode) \
void name (typelist *list, typenode *node, typenode *newNode);

#define GEN_DLL_INSERTBEGINNING_D(name, nameinsertbefore, typelist, typenode) \
void name (typelist *list, typenode *newNode);

#define GEN_DLL_INSERTEND_D(name, nameinsertbeginning, nameinsertafter, typelist, typenode) \
void name (typelist *list, typenode *newNode);

#define GEN_DLL_REMOVE_D(name, typelist, typenode) \
typenode *name (typelist *list, typenode *node);

#define GEN_DLL_NEWNODE_D(name, typedata, typenode) \
typenode *name (typedata data);

#define GEN_DLL_FREENODE_D(name, typenode) \
int name (typenode *node);

#define GEN_DLL_NEWLIST_D(name, typelist) \
typelist *name ();

#define GEN_DLL_FREELIST_D(name, namedllfreenode, typelist, typenode) \
int name (typelist *list);

#define GEN_DLINKEDLIST_FUNCTIONS_DECLARATION(name, typelist, typenode, typedata) \
GEN_DLL_INSERTAFTER_D(name##_insertafter, typelist, typenode); \
GEN_DLL_INSERTBEFORE_D(name##_insertbefore, typelist, typenode); \
GEN_DLL_INSERTBEGINNING_D(name##_insertbeginning, name##_insertbefore, typelist, typenode); \
GEN_DLL_INSERTEND_D(name##_insertend, name##_insertbeginning, name##_insertafter, typelist, typenode); \
GEN_DLL_REMOVE_D(name##_remove, typelist, typenode); \
GEN_DLL_NEWNODE_D(name##_newnode, typedata, typenode); \
GEN_DLL_FREENODE_D(name##_freenode, typenode); \
GEN_DLL_NEWLIST_D(name##_newlist, typelist); \
GEN_DLL_FREELIST_D(name##_freelist, name##_freenode, typelist, typenode);
/**/

#define GEN_DLINKEDLIST_FUNCTIONS(name, typelist, typenode, typedata) \
GEN_DLL_INSERTAFTER(name##_insertafter, typelist, typenode); \
GEN_DLL_INSERTBEFORE(name##_insertbefore, typelist, typenode); \
GEN_DLL_INSERTBEGINNING(name##_insertbeginning, name##_insertbefore, typelist, typenode); \
GEN_DLL_INSERTEND(name##_insertend, name##_insertbeginning, name##_insertafter, typelist, typenode); \
GEN_DLL_REMOVE(name##_remove, typelist, typenode); \
GEN_DLL_NEWNODE(name##_newnode, typedata, typenode); \
GEN_DLL_FREENODE(name##_freenode, typenode); \
GEN_DLL_NEWLIST(name##_newlist, typelist); \
GEN_DLL_FREELIST(name##_freelist, name##_freenode, typelist, typenode);

#endif
